#include "PropertySheet.h"

namespace FinalRendering
{
	namespace Editor
	{
		using namespace GxRendering::UI;

		PropertyItem::PropertyItem(const String & name, const String & value, bool pickable, bool readonly)
		{
			lblTitle = new Label();
			lblValue = new Label();
			
			SetName(name);
			SetValue(value);
			Pickable = pickable;
			ReadOnly = readonly;
		}

		String PropertyItem::GetName()
		{
			return Name;
		}

		String PropertyItem::GetValue()
		{
			return Value;
		}

		void PropertyItem::SetName(const String & name)
		{
			Name = name;
			lblTitle->SetText(Name);
		}

		void PropertyItem::SetValue(const String & value)
		{
			Value = value;
			lblValue->SetText(Value);
		}

		void PropertyItem::Draw(int x, int y, int w, int titleWidth, int h, bool drawValue)
		{
			Rect r(x,y, titleWidth, h);
			Global::ClipRects->AddRect(r);
			lblTitle->Draw(x+5, y+2);
			Global::ClipRects->PopRect();
			r.x = x + titleWidth;
			r.w = w-titleWidth -2;
			if (drawValue)
			{
				Global::ClipRects->AddRect(r);
				lblValue->Draw(x+titleWidth + 2, y+2);
				Global::ClipRects->PopRect();
			}
			Graphics::PenColor = Color(200,200,200,255);
			Graphics::DrawLine(x, y+h, x+w, y+h);
			Graphics::DrawLine(x+titleWidth, y, x+titleWidth, y+h);
		}


		PropertySheet::PropertySheet()
		{
			BackColor = Color(255,255,255,255);
			BorderStyle = BS_LOWERED;
			titleWidth = 80;
			Margin = 2;
			sb = new ScrollBar2();
			sb->SetWidth(17);
			sb->DockStyle = Control::dsRight;
			sb->Visible = false;
			sb->SetOrientation(SO_VERTICAL);
			text = new TextBox();
			btnPick = new Button();
			btnPick->SetText(L"...");
			btnPick->OnClick.Bind(this,&PropertySheet::btnPickClicked);
			AddChild(text);
			AddChild(btnPick);
			AddChild(sb);
			text->BorderStyle = BS_NONE;
			text->Visible = false;
			btnPick->Visible = false;
			SelectedIndex = -1;
			text->SetFont(GxRendering::Font(_T("Tahoma"),9));
			text->OnLostFocus.Bind(this, &PropertySheet::TextLostFocus);
		}

		void PropertySheet::btnPickClicked(GxRendering::UI::UI_Base * sender)
		{
			if (SelectedIndex != -1)
				PickProperty.Invoke(items[SelectedIndex]->GetName());
		}

		void PropertySheet::AddPropertyItem(FinalRendering::Editor::PropertyItem * item)
		{
			items.Add(item);
		}

		void PropertySheet::Clear()
		{
			SelectedIndex = -1;
			items.Clear();
			ChangeSelectedIndex(-1);
		}

		void PropertySheet::Draw(int absX, int absY)
		{
			if (!Visible)
				return;
			Control::Draw(absX,absY);
			Global::ClipRects->AddRect(Rect(absX, absY+2, Width, Height));
			Container::Draw(absX, absY);
			Global::ClipRects->PopRect();
			absX += Left;
			absY += Top;
			PositEditControl();
			for (int i=sb->GetPosition(); i<items.Count(); i++)
			{
				int y = (i-sb->GetPosition())*ItemHeight;
				items[i]->Draw(absX, absY+y, clientRect.w, titleWidth, ItemHeight, (SelectedIndex != i));
			}
		}

		void PropertySheet::SizeChanged()
		{
			int pageSize = Height / ItemHeight;
			int Max = items.Count() - pageSize;
			if (Max > 0)
			{
				int pos = sb->GetPosition();
				if (pos > Max)
					pos = Max;
				sb->SetValue(0,Max,pos, pageSize);
				sb->Visible = true;
			}
			else
			{
				sb->SetPosition(0);
				sb->Visible = false;
			}
			Container::SizeChanged();
			PositEditControl();
		}

		void PropertySheet::PositEditControl()
		{
			if (SelectedIndex >= items.Count() || SelectedIndex <0)
				return;
			PropertyItem * item = items[SelectedIndex].operator ->();
			int top = (SelectedIndex-sb->GetPosition())*ItemHeight;
			if (item->Pickable)
			{
				btnPick->Posit(clientRect.w-16-1,top+1, 16,16);
				btnPick->Visible = true;
			}
			else
				btnPick->Visible = false;
			text->Visible = true;
			text->Posit(titleWidth-2, top-4, clientRect.w-titleWidth-2-(btnPick->Visible?btnPick->GetWidth()+1:0), ItemHeight+2);
		}

		void PropertySheet::SetProperty(const String & propName, const String & value)
		{
			int fid = -1;
			for (int i=0; i<items.Count(); i++)
				if (items[i]->GetName() == propName)
				{
					fid = i;
					break;
				}
			if (fid == -1)
				return;
			UpdateProperty(fid, value);
		}

		void PropertySheet::UpdateProperty(int id, const String & value)
		{
			if (value == lstText)
				return;
			bool succ = true;
			PropertyChanged.Invoke(items[id]->GetName(), value, succ);
			if (succ)
			{
				items[id]->SetValue(value);
				if (SelectedIndex == id)
					text->SetText(value);
			}
		}

		void PropertySheet::ChangeSelectedIndex(int selID)
		{
			if (selID >= items.Count())
				selID = -1;
			if (selID < 0)
				selID = -1;
			if (SelectedIndex != -1 && selID != SelectedIndex)
			{
				UpdateProperty(SelectedIndex, text->GetText());
			}
			SelectedIndex = selID;
			if (SelectedIndex == -1)
			{
				text->Visible = false;
				btnPick->Visible = false;
			}
		}

		void PropertySheet::DoMouseDown(int X, int Y, SHIFTSTATE Shift)
		{
			Container::DoMouseDown(X,Y,Shift);
			if (!Visible || !Enabled)
				return;
			if (!DownInRect)
			{
				ChangeSelectedIndex(-1);
				return;
			}
			if (sb->Visible && X-Left>Width-sb->GetWidth())
				return;
			ChangeSelectedIndex(Y/ItemHeight + sb->GetPosition());
			if (SelectedIndex != -1)
			{
				text->SetText(items[SelectedIndex]->GetValue());
				lstText = text->GetText();
				PositEditControl();
				text->DoMouseDown(X-Left,Y-Top,Shift);
			}
		}

		void PropertySheet::DoMouseUp(int X, int Y, SHIFTSTATE Shift)
		{
			Container::DoMouseUp(X,Y,Shift);
		}

		void PropertySheet::DoMouseMove(int X, int Y)
		{
			Container::DoMouseMove(X,Y);
		}

		void PropertySheet::DoKeyDown(unsigned short Key, GxRendering::UI::SHIFTSTATE Shift)
		{
			Container::DoKeyDown(Key, Shift);
			if (Key == VK_ESCAPE)
			{
				if (SelectedIndex != -1 && text->Visible)
				{
					text->SetText(items[SelectedIndex]->GetValue());
				}
			}
		}

		void PropertySheet::TextLostFocus(GxRendering::UI::UI_Base * sender)
		{
			ChangeSelectedIndex(-1);
		}
	}
}